package voting;

import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.net.Socket;
import java.util.Arrays;
import java.util.Calendar;

import GUI.MainFrame;

import network.Client;
import network.Operations;
import network.Server;
import network.ServerConnection;
import encryption.Paillier;
import encryption.RSA;
import entities.Candidate;
import entities.User;
import entities.Voting;

public class ClientVoting {


	public static Voting [][] currentVotings;
	public static  Voting votingChosen;

	public static  Candidate[] candidates;

	public ClientVoting(){

	}
	/** Class Candidates Needs To be Constructed 
	Consider adding a list of Voters after 
	updating the database to show the allowed voters for this voting
	 **/
	public static boolean  createVoting(int sDay,int sMonth,int sYear,int eDay,int eMonth,int eYear,User[] voters, Candidate[] candidates, String question,int maxCandidates){

		//no of candidates that can be chosen in a vote by default 1

		String message=Operations.CREATE_VOTING+" "+sDay+"#"+sMonth+"#"+sYear+"#"+eDay+"#"+eMonth+"#"+eYear+"#"+1000+"#"+candidates.length+"#"+maxCandidates+"#"+question+"#";
		//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%5
		for(int i=0;i<candidates.length-1;i++)
			if(candidates[i]!=null)
				
				  message+=candidates[i].getName()+"-"+candidates[i].getProgram()+"#";
				
				
		//has to chose at least one candidate
		if(candidates.length>0)
			if(candidates[candidates.length-1]!=null)
				message+=candidates[candidates.length-1].getName()+"-"+candidates[candidates.length-1].getProgram();
				
				

		Client.client.sendMessage(message);
		System.out.println("send message "+message);
		String confirm=Client.client.receiveMessage();
		if(confirm.equals(Operations.CREATE_VOTING_COMPLETE+""))
		{
			System.out.println("Voting created successfully");
			return true;
		}
		else
		{
			if(confirm.equals(Operations.CREATE_VOTING_FAILED+""))
				System.out.println("Voting creation failed");
			return false;
		}

	}


	/** use the Object Voting to view the voting choosen (Voting Name, Voting Candidates, and Voting Question) **/
	public static Voting viewVoting(int votingID,int adminID){

		Client.client.sendMessage(Operations.SELECT_VOTING+" "+votingID+" "+adminID);

		String votingMessage=Client.client.receiveMessage();
		String[] tokens=votingMessage.split(" ");
		//split on what

		if(tokens[0].equals(Operations.SELECT_VOTING_COMPLETE+""))
		{
			votingChosen=new Voting();
			String [] next=votingMessage.substring((Operations.SELECT_VOTING_COMPLETE+"").length()).split("#");
			votingChosen.setQuestions(next[0]);
			votingChosen.setAdminID(adminID);
			votingChosen.setVotingID(votingID);
			votingChosen.setPublicKey(next[1]);
			votingChosen.setNumberOfVoters(Integer.parseInt(next[2]));
			votingChosen.setResult(next[3]);
			candidates=new Candidate[Integer.parseInt(next[4])];
			int j=0;
			for(int i=5;i<next.length-1;i+=2)
			{
				candidates[j]=new Candidate();
				candidates[j].setCandidateID(Integer.parseInt(next[i]));
				candidates[j].setName(next[i+1]);
				j++;

			}

			System.out.println(Arrays.toString(candidates));
			System.out.println("Select voting complete "+votingMessage);
		}
		else
			System.out.println("Select voting failed");

		return votingChosen;
	}

	/** This method should be used to view all the votings this user either created or voted in **/
	public static Voting[][] getAllVotings(){
		try
		{
			Voting[][] votings=new Voting[2][];
			votings[0]=new Voting[0];
			votings[1]=new Voting[0];
			Client.client.sendMessage(Operations.GET_ALL_VOTINGS+"");
			String votingMessage=Client.client.receiveMessage();
			System.out.println(votingMessage);
			String [] messageContents=votingMessage.split("&");
			if(messageContents.length>0)
			{
				String [] previous=messageContents[0].split("-");
				System.out.println(Arrays.toString(messageContents));
		String[] pending=new String[0];
		if(messageContents.length>1)
			pending=messageContents[1].split("-");
				if(messageContents[0].length()!=0)
					votings[0]=new Voting[previous.length];
		if(messageContents.length>1&&messageContents[1].length()!=0)
					votings[1]=new Voting[pending.length];

				for(int i=0;i<votings[0].length;i++)
				{
					String [] temp=previous[i].split("#");
					Voting tempVoting=new Voting();
					tempVoting.setVotingID(Integer.parseInt(temp[0].trim()));
					tempVoting.setAdminID(Integer.parseInt(temp[1].trim()));
					tempVoting.setQuestions(temp[2]);
					votings[0][i]=tempVoting;
				}
				for(int i=0;i<votings[1].length;i++)
				{
					String [] temp=pending[i].split("#");
					Voting tempVoting=new Voting();
					tempVoting.setVotingID(Integer.parseInt(temp[0].trim()));
					tempVoting.setAdminID(Integer.parseInt(temp[1].trim()));
					tempVoting.setQuestions(temp[2]);
					votings[1][i]=tempVoting;
				}
			}
			currentVotings=votings;
			return votings;
		}
		catch(Exception e)
		{
			e.printStackTrace();
		}
		return null;


	}
	/** This method is used to view the votings of each user **/
	public static  String getVote(){


		Client.client.sendMessage(Operations.GET_VOTE+" "+votingChosen.getVotingID()+" "+votingChosen.getAdminID());

		String voteMessage=Client.client.receiveMessage();

		String tokens[]=voteMessage.split(" ");
		String voteHash=null;
		System.out.println(voteMessage);
		if(tokens[0].equals(Operations.GET_VOTE_COMPLETE+""))
		{

			voteHash=tokens[1];
			System.out.println("User's vote "+voteHash);
		}
		else
			System.out.println("User didn't vote yet");

		return voteHash;
	}
	public static String[] getAllVotes(int adminID,int votingID)
	{
		Client.client.sendMessage(Operations.GET_ALL_VOTES+" "+"-1"+" "+votingID);
		String message=Client.client.receiveMessage();
		if(message.equals(""))
			message = "No Votes Yet_ #";
		String [] votes = message.split("#");
		return votes;
	}
	public static String getPublicKey(int votingID)
	{
		Client.client.sendMessage(""+Operations.GET_PUBLIC_KEY+" "+votingID);
		String receivedMessageEncrypted = null;
		try {
			receivedMessageEncrypted = new String(Client.client.receiveRSAMessage() , "ISO-8859-1");
		} catch (UnsupportedEncodingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		String keyMod = MainFrame.getMainFrame().serverPublicKeyMod;
		String keyExp = MainFrame.getMainFrame().serverPublicKeyExp;
		String message = new RSA().rsadecryptPublic(receivedMessageEncrypted, keyMod, keyExp);
		System.out.println("Public Key "+message);
		if(!message.split(" ")[1].equals("This#is#the#server"))return null;
		return message.split(" ")[0];
	}
	public static String calculateSum(int adminID,int votingID)
	{
		Client.client.sendMessage(""+Operations.CALCULATE_SUM);
		Client.client.receiveMessage();
		Client.client.sendMessage(Operations.CALCULATE_SUM+" "+adminID+" "+votingID);
		return Client.client.receiveMessage();
	}
	/** This Method is responsible for making the vote of the user **/

	public static Candidate [] getCandidates(Voting v)
	{
		Client.client.sendMessage(""+Operations.GET_CANDIDATES+" "+v.getVotingID());
		String message = Client.client.receiveMessage();
		String [] result = message.split("#");
		Candidate [] candidates = new Candidate[result.length];
		for(int i = 0 ; i<candidates.length ;++i)
		{
			String [] c = result[i].split("_");
			candidates[i] = new Candidate();
			candidates[i].setCandidateID(new Integer(c[0]));
			candidates[i].setName(c[1]);
			candidates[i].setProgram(c[2]);
		}
		return candidates;
	}
	public static  String makeVote(int[]candidatesChosen){

		boolean [] votes=new boolean[candidates.length];
		for(int i=0;i<candidates.length;i++)
		{
			boolean flag=false;
			for(int j=0;j<candidatesChosen.length;j++)
			{
				if(candidatesChosen[j]==candidates[i].getCandidateID())
				{flag=true; break;}
			}
			votes[i]=flag;
		}
		Paillier paillier=new Paillier();
		String pubKey = getPublicKey(votingChosen.getVotingID());
		if(pubKey == null)return null;
		String[] keyParameters=pubKey.split("-");
		BigInteger n=new BigInteger(keyParameters[0]);
		BigInteger g=new BigInteger(keyParameters[1]);	 
		paillier.setPublicKey(n, g);
		BigInteger msg=paillier.createMessage(votes, 1000);

		BigInteger encryptedVote=paillier.encrypt(msg);
		String voteHash=encryptedVote.toString();
		String messageToEncrypt = votingChosen.getVotingID()+" "+votingChosen.getAdminID()+" "+voteHash + " " + Client.client.getRandomPassword();
		String message=Operations.VOTE+" ";

		Client.client.sendMessage(message);
		Client.client.receiveMessage();
		String keyMod = MainFrame.getMainFrame().serverPublicKeyMod;
		String keyExp = MainFrame.getMainFrame().serverPublicKeyExp;
		
		byte[] encryptedMessage = new RSA().rsaEncryptToBytes(messageToEncrypt,keyMod , keyExp);
		Client.client.sendRSAMessage(encryptedMessage);
		
		String confirm=Client.client.receiveMessage();
		String[] tokens=confirm.split(" ");
		if(tokens[0].equals(Operations.VOTE_COMPLETE+""))
		{
			System.out.println("vote completed "+voteHash);
		}
		else
			if(tokens[0].equals(Operations.VOTE_FAILED+""))
			{
				System.out.println("vote failed");
				voteHash=null;
			} 
			else
			{
				System.out.println("already voted before");
				voteHash = "T"+voteHash;
			}
		///have to confirm that it was counted
		return voteHash;
	}
	public static void main(String [] args)
	{

		/*Client.client = new Client();
		Client.client.connect();
	    Client.client.sendMessage(Operations.USER_VIEW+"");
		Client.client.receiveMessage();
		ClientVoting.viewVoting(13, 1);
		System.out.println("my vote " +ClientVoting.makeVote(new int[]{14}));
		 */

		Voting[][] votings=new Voting[2][];
		votings[0]=new Voting[0];
		votings[1]=new Voting[1];

		String votingMessage="&1";
		System.out.println(votingMessage);
		String [] messageContents=votingMessage.split("&");
		if(messageContents.length>0)
		{
			String [] previous=messageContents[0].split("-");
			System.out.println(Arrays.toString(messageContents));
			String [] pending=messageContents[1].split("-");

			if(messageContents[0].length()!=0)
				votings[0]=new Voting[previous.length];
			if(messageContents[1].length()!=0)
				votings[1]=new Voting[pending.length];

			for(int i=0;i<votings[0].length;i++)
			{
				String [] temp=previous[i].split("#");
				Voting tempVoting=new Voting();
				tempVoting.setVotingID(Integer.parseInt(temp[0].trim()));
				tempVoting.setAdminID(Integer.parseInt(temp[1].trim()));
				tempVoting.setQuestions(temp[2]);
				votings[0][i]=tempVoting;
			}
			for(int i=0;i<votings[1].length;i++)
			{
				String [] temp=pending[i].split("#");
				Voting tempVoting=new Voting();
				tempVoting.setVotingID(Integer.parseInt(temp[0].trim()));
				tempVoting.setAdminID(Integer.parseInt(temp[1].trim()));
				tempVoting.setQuestions(temp[2]);
				votings[1][i]=tempVoting;
			}
		}

	}

}
